-
Notifications
You must be signed in to change notification settings - Fork 800
SOLR-17600 Replaces MapSerializable with MapWriter #4011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…across Solr codebase
…` across Solr codebase
…serialization consistency
…proved map serialization consistency
…d serialization consistency
…Map` for consistency in plugin and handler serialization
…plugin serialization consistency
…tter readability and consistency
…deredMap` for consistent serialization in config and handler classes
…plugin and component info serialization with `SimpleOrderedMap`
| Map deepCopy = Utils.getDeepCopy(data, 3); | ||
| Map p = (Map) deepCopy.get(NAME); | ||
| if (p == null) deepCopy.put(NAME, p = new LinkedHashMap<>()); | ||
| if (paramSet == null) p.remove(name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this if should have { } to match the else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that in Java conditionals should always use curly braces for clarity. This is the existing code that was not changed in my PR.
I am hesitant to change it as I am not sure if there is a convention regarding this practice in the project.
| "cacheControl", | ||
| cacheControlHeader); | ||
| public void writeMap(EntryWriter ew) throws IOException { | ||
| ew.put("never304", never304) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is nicer pattern, less a "unique magic pattern".
|
|
||
| public static CreateCoreParams createRequestBodyFromV1Params(SolrParams solrParams) { | ||
| final var v1ParamMap = solrParams.toMap(new HashMap<>()); | ||
| final var v1ParamMap = new SimpleOrderedMap<>(solrParams); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a subtle semantic difference here. Previously, we had a bonafide Map. If there were duplicate keys, the last value wins (looking at Utils.convertToMap, called by toMap). Probably wasn't intended but there is integrity of the Map contract at least. The constructor you use assumes the input has no duplicate keys. They will be added, and SimpleOrderedMap will not quite act exactly like a Map. I'm not sure what the final effect is without trying/testing. We could change SimpleOrderedMap's constructor here to have a hack for the NamedList (that isn't SimpleOrderedMap) case. Or don't use SimpleOrderedMap here, which I can see was chosen for your convenience, not because it's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced with Utils.convertToMap.
…CreateCore` for parameter handling simplification
dsmiley
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from just removing a redundant abstraction, this change should have the benefit of removing intermediate needless data structures (Maps/NamedList/SimpleOrderedMap). But I'm seeing here a continuation of that.
The only place we need the data structure is where toMap was being called. Perhaps it'd be ideal to split this huge PR in two -- first address toMap callers, then the rest.
| Map<String, Object> config = p.initArgs.toMap(new HashMap<>()); | ||
| Map<String, Object> config = new SimpleOrderedMap<>(p.initArgs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, avoid NamedList/SimpleOrderedMap
How about p.initArgs.asMap(0)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed as requested
| CoreAdminParams.ACTION, CoreAdminParams.CoreAdminAction.INSTALLCOREDATA.toString()); | ||
| typedMessage.toMap(new HashMap<>()).forEach((k, v) -> coreApiParams.set(k, v.toString())); | ||
|
|
||
| new SimpleOrderedMap<>(typedMessage).forEach((k, v) -> coreApiParams.set(k, v.toString())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typedMessage._forEachEntry here instead
(avoiding senseless intermediate data structure creation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
| new NamedList<>(attributes).writeMap(ew); | ||
| if (initArgs != null) { | ||
| new SimpleOrderedMap<>(initArgs).writeMap(ew); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not create a new Map just to ultimately write it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed caused test failures. Unsure why. Error was cannot cast LinkedHashMap to String however stack trace was unclear as to location of exception.
Reverted change.
| if (paramSet == null) p.remove(name); | ||
| else p.put(name, paramSet.toMap(new LinkedHashMap<>())); | ||
| else { | ||
| p.put(name, new SimpleOrderedMap<>(paramSet)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one's fine
…ap serialization and entry iteration to simplify code and improve readability
|
@dsmiley I followed the advice in the comments however I had test failures in solr:core after pushing changes. Reverted changes to PluginInfo and tests are passing on my Codespaces instance. I don't think the solr:core tests ran for the last commit. I guess it is restricted due to heavy resource use. |
| @@ -0,0 +1,7 @@ | |||
| title: SOLR 17600 - Replace MapSerializable with MapWriter | |||
| type: changed | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactorings are "other".
I'm not happy with the logchange plugin constraining the enum choices here
| ew.put( | ||
| tag, | ||
| new SimpleOrderedMap<>( | ||
| m -> { | ||
| new NamedList<>(items).writeMap(m); | ||
| })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what I'm looking at here
|
|
||
| messageTyped.validate(); | ||
| return new ZkNodeProps(messageTyped.toMap(new HashMap<>())); | ||
| return new ZkNodeProps((Map<String, Object>) new SimpleOrderedMap<>(messageTyped)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally, we should avoid creating a SimpleOrderedMap. Use Utils.convertToMap instead.
A SimpleOrderedMap is okay to add to a MapWritable entry though, or any similar place for a response-writing use-case. A SimpleOrderedMap does not hash its data, so has O(N) access. It's designed for writing out data that will unlikely have its keys looked up. It's not a general replacement for a Map.
https://issues.apache.org/jira/browse/SOLR-17600
Description
This pull request replaces the deprecated
MapSerializableinterface withMapWriteracross the Solr codebase.MapSerializablerelied on thetoMap(Map)pattern, which often led to unnecessary object allocations and inconsistent serialization behavior. By migrating toMapWriterand itswriteMap(EntryWriter)pattern, we improve memory efficiency and ensure more consistent serialization across different formats like JavaBin and JSON.Solution
The migration involved several key steps:
MapSerializableinterface and removed its usage from theMapWriterinterface.MapWriternow serves as the primary interface for object-to-map serialization.MapWriterinstead ofMapSerializable. Key areas include:SolrConfig,PluginInfo,SolrIndexConfig,CacheConfig,ConfigOverlay,RequestParams,IndexSchema.CreateCore,InstallShardData,MigrateDocsAPI,ModifyCollectionAPI,MoveReplicaAPI,SplitShardAPI, and more.ZkNodeProps,IndexFingerprint.toMap(Map<String, Object> map)implementations towriteMap(EntryWriter ew). This allows for direct writing to the underlying data structure (likeJavaBinCodec's output stream) without necessarily creating intermediateMapobjects.Utils.convertToMap,Utils.reflectToMap, and other utility methods to support the new pattern.Utils.makeDeepCopynow usesSimpleOrderedMapwithMapWriterfor better efficiency.toMapcalls and simplified serialization logic in several handlers and components. UpdatedJavaBinCodec,TextWriter, andJSONWriterto optimize forMapWriter.Tests
Existing tests were updated to accommodate the change in serialization:
TestConfig,SolrIndexConfigTest,CacheConfigTest, andNodeConfigClusterPluginsSourceTestto verify that the configuration objects are still correctly serialized.TestSchemaDesignerAPIandSolrExampleCborTestto ensure API and serialization consistency.JavaBinCodecandJSONWritercorrectly handle the newMapWriterimplementations.Checklist
Please review the following and check all that apply:
mainbranch../gradlew check.